#ifndef HMACRO_H
#define HMACRO_H

#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/facilities/apply.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>

//----------DEFAULT TYPES--------------------

#define MAX_ARG     10

#define EMPTYSEQ    BOOST_PP_EMPTY()

#define FNENUMTYPESEQ(z, n, data)     (APPENDN(z, n, data))
#define FNENUMTYPE  \
  BOOST_PP_REPEAT(MAX_ARG, FNENUMTYPESEQ, FUNCTION)


#define FNTYPEMAPSEQ(z, n, data)     ((APPENDN(z, n, data)) EMPTYSEQ)
#define FNTYPEMAP  \
  BOOST_PP_REPEAT(MAX_ARG, FNTYPEMAPSEQ, Function)

#define FNTYPESYMBOLSEQ(z, n, data)  (APPENDN(z, n, data))
#define FNTYPESYMBOL				\
  BOOST_PP_REPEAT(MAX_ARG, FNTYPESYMBOLSEQ, fn)

#define FNTYPEFORMATFNSEQ(z, n, data)   FNTYPEMAPSEQ(z, n, data)
#define FNTYPEFORMATFN  \
  BOOST_PP_REPEAT(MAX_ARG, FNTYPEMAPSEQ, Fn)
//********************************************

//----------SEQUENCE TRANSFORMATION----------

#define CONCATSEQ( To, From )			\
  BOOST_PP_APPLY( (To) )BOOST_PP_APPLY( (From) )



//*********************************************

//----------GENERIC FUNCTIONS----------------

#define UNSIGNEDSEQ(r, data, element)     (PREPENDN(r, data, element))
#define UNSIGNED( seq )				\
  BOOST_PP_SEQ_FOR_EACH(UNSIGNEDSEQ, u , seq )

#define POINTERSEQ(r, data, element)     (PREPENDN(r, data, element))
/* #define POINTER( seq )				\ */
/*   BOOST_PP_SEQ_FOR_EACH(POINTERSEQ, _, seq ) */

#define UNSIGNEDVERSION(z, n, data) \
  (UNSIGNED((EXTRACTKEY(BOOST_PP_SEQ_ELEM(n,data))))	\
   MAPTO_LOCALTYPE(unsigned, BOOST_PP_SEQ_ELEM(n, data))	\
   )
#define POINTERVERSION(z, n, data) \
  (POINTER((EXTRACTKEY(BOOST_PP_SEQ_ELEM(n,data))))	\
   MAPTO_LOCALTYPE(*, BOOST_PP_SEQ_ELEM(n, data)))


#define APPENDN(z, n, data)     BOOST_PP_CAT(data, n)
#define PREPENDN(z, n, data)     BOOST_PP_CAT(n, data)


#define EXTRACTKEY( seq )	\
  BOOST_PP_SEQ_HEAD( seq ) 
#define EXTRACTVALUE( seq )     \
  BOOST_PP_IF( BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(seq), 1), \
	       BOOST_PP_SEQ_ELEM( BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(seq),\
					       1), \
				  seq ), \
	       EMPTYSEQ )

#define MAPTO_LOCALTYPE(keyword,  seq )			\
  BOOST_PP_IF( BOOST_PP_SUB(BOOST_PP_SEQ_SIZE( seq ), 1),	\
	       (keyword EXTRACTVALUE( seq )),			\
	       EMPTYSEQ						\
	       )


#endif
